from flask_appbuilder.models.filters import BaseFilter
from flask_appbuilder.models.sqla.filters import get_field_setup_query

from . import db
from flask import render_template
from flask import g
from flask import request
from flask_appbuilder import ModelView
from flask_appbuilder import action
from flask_appbuilder import BaseView, expose, has_access
from flask_appbuilder.models.sqla.interface import SQLAInterface
from flask_appbuilder.fieldwidgets import BS3TextFieldWidget
from .models import Participant, Event, EventGroup, MyUser
from app import appbuilder
from sqlalchemy import func

"""
    Application wide 404 error handler
"""


@appbuilder.app.errorhandler(404)
def page_not_found(e):
    return (
        render_template(
            "404.html", base_template=appbuilder.base_template, appbuilder=appbuilder
        ),
        404,
    )


db.create_all()


class BS3TextFieldROWidget(BS3TextFieldWidget):
    def __call__(self, field, **kwargs):
        kwargs['readonly'] = 'true'
        return super(BS3TextFieldROWidget, self).__call__(field, **kwargs)


def get_user_location():
    return g.user.extra


def get_user():
    return g.user


class ParticipantView(ModelView):
    datamodel = SQLAInterface(Participant)
    label_columns = {'user': '参与人员', 'pay': '支付金额', 'spend_share': '花费比例', "spend": '花费金额',
                     "balance": "应收金额"}
    list_title = '参与者'
    edit_title = '编辑参与人员'
    add_title = '添加参与人员'
    show_title = '显示参与人员'
    show_columns = ['user_name', 'spend_share', 'pay', 'spend', 'balance']
    list_columns = ['user_name', 'spend_share', 'pay', 'spend', 'balance']
    edit_columns = ['user', 'spend_share', 'pay']
    add_columns = ['spend_share', 'pay', 'user']

    def pre_add(self, item):
        item.event_id = int(request.args.get("_flt_0_event"))

    def post_add(self, item):
        self.update_event_participant(item)

    def post_delete(self, item):
        self.update_event_participant(item)

    def post_update(self,item):
        self.update_event_participant(item)

    def update_event_participant(self, item):
        amount = db.session.query(func.sum(Participant.pay)).filter(
            Participant.event_id == item.event_id).scalar()
        shares = db.session.query(func.sum(Participant.spend_share)).filter(
            Participant.event_id == item.event_id).scalar()
        ps = db.session.query(Participant).filter(Participant.event_id == item.event_id).all()
        for p in ps:
            p.spend = p.spend_share * amount / shares
            p.balance = p.pay - p.spend
            db.session.add(p)
        item.event.amount = amount
        db.session.add(item.event)
        db.session.commit()


class EventView(ModelView):
    datamodel = SQLAInterface(Event)
    label_columns = {'amount': '活动总计金额',"participant_facts":"参与情况", 'date': '日期', 'description': '活动名称', }
    related_views = [ParticipantView, ]
    list_title = '活动'
    edit_title = '编辑活动'
    add_title = '添加活动'
    show_title = '显示活动'
    show_columns = ['description', 'amount', 'date']
    list_columns = ['description', 'date', 'amount','participant_facts']
    edit_columns = ['description', 'amount', 'date']
    add_columns = ['description', 'amount', 'date']
    show_template = 'appbuilder/general/model/show_cascade.html'

    def pre_add(self, item):
        item.group_id = int(request.args.get("_flt_0_group"))


def get_my_parts_in_group(group_id):
    data = ""
    events = db.session.query(Event) \
        .filter(Event.group_id == group_id).all()
    for event in events:
        parts = db.session.query(Participant) \
            .filter(Participant.event_id == event.id).all()
        i_am_in = False
        balance = 0
        part_names = ""
        for part in parts:
            if part.user_id == g.user.id:
                balance = part.balance
                i_am_in = True
            part_names = part_names + \
                         part.user.last_name + \
                         part.user.first_name + ", "
        if i_am_in:
            data = data + "['" \
                   + event.description + "','" \
                   + str(event.date) + "','" \
                   + part_names + "','" \
                   + str(balance) \
                   + "'],"
    return data


class FilterContainFunction(BaseFilter):
    name = "Filter view where field is in a list returned by a function"
    arg_name = "inf"

    def apply(self, query, func):
        query, field = get_field_setup_query(query, self.model, self.column_name)
        return query.filter(field.contains(func()))


class EventGroupView(ModelView):
    datamodel = SQLAInterface(EventGroup)
    related_views = [EventView, ]
    list_title = '活动组'
    edit_title = '编辑活动组'
    add_title = '添加活动组'
    show_title = '显示活动组'
    label_columns = {'date': '日期', 'title': '活动组名称', 'users': '参与人员'}
    add_columns = ['title', 'date', 'users']
    show_columns = ['title', 'date', 'users']
    list_columns = ['title', 'date', 'users']
    edit_columns = ['title', 'date', 'users']
    show_template = 'appbuilder/general/model/show_cascade.html'
    base_filters = [['users', FilterContainFunction, get_user]]

    @action("ViewGroupMyParts", "查看活动组的活动应收支款", "查看活动组的活动应收支款?", "fa-rocket")
    def view_group_my_parts(self, items):
        if isinstance(items, list):
            items = items[0]
        get_my_parts_in_group(items.id)
        event_ids = db.session.query(Event.id) \
            .filter(Event.group_id == items.id).order_by(Event.date).all()
        event_ids = [event_id[0] for event_id in event_ids]
        amount = db.session.query(func.sum(Participant.balance)) \
            .filter(Participant.event_id.in_(event_ids)) \
            .filter(Participant.user_id == g.user.id).scalar()

        return render_template('event_balance.html', ds=get_my_parts_in_group(items.id), param1=str(amount),
                               base_template=appbuilder.base_template,
                               appbuilder=appbuilder)


appbuilder.add_view_no_menu(ParticipantView)
appbuilder.add_view_no_menu(EventView)
appbuilder.add_view(EventGroupView, "活动组列表", icon="fa-folder-open-o", category="AA制记录")


def get_my_parts():
    data = ""
    events = db.session.query(Event).order_by(Event.date).all()
    for event in events:
        parts = db.session.query(Participant) \
            .filter(Participant.event_id == event.id).all()
        i_am_in = False
        balance = 0
        part_names = ""
        for part in parts:
            if part.user_id == g.user.id:
                balance = part.balance
                i_am_in = True
            part_names = part_names + part.user.last_name + part.user.first_name +  ", "
        if i_am_in:
            data = data + "['" \
                   + event.description + "','" \
                   + str(event.date) + "','" \
                   + part_names + "','" \
                   + str(balance) \
                   + "'],"
            print(data)
    return data


class MyView(BaseView):
    # 路由基础
    route_base = '/myview'
    # 默认视图
    default_view = 'all_my_parts'

    @expose('/all_my_parts')
    @has_access
    def all_my_parts(self):
        # 查询每个用户的余额
        amount = db.session.query(func.sum(Participant.balance)) \
            .filter(Participant.user_id == g.user.id).scalar()
        # 渲染模板
        return render_template('event_balance.html', ds=get_my_parts(),
                               param1=str(amount),
                               base_template=appbuilder.base_template,
                               appbuilder=appbuilder)

appbuilder.add_view(MyView, "所有参与活动", category="个人")

